import os
import torch
from dotenv import load_dotenv
import logging
from typing import Optional, Any

load_dotenv()

logger = logging.getLogger(__name__)

def get_bool_env(key: str, default: bool = False) -> bool:
    """从环境变量获取布尔值"""
    value = os.getenv(key, str(default)).lower()
    return value in ('true', '1', 'yes', 'on')

class ConfigManagerProxy:
    """配置管理器代理 - 提供新旧配置系统的统一接口"""

    def __init__(self):
        self._config_manager = None
        self._fallback_enabled = True  # 当配置管理器不可用时回退到环境变量

    async def initialize(self, db_config: Optional[dict] = None):
        """异步初始化配置管理器"""
        try:
            if db_config:
                from core.config import ConfigManager
                self._config_manager = ConfigManager(db_config)
                success = await self._config_manager.initialize()
                if success:
                    logger.info("Config manager initialized successfully")
                    return True
                else:
                    logger.warning("Config manager initialization failed, using fallback")
                    self._config_manager = None
                    return False
        except Exception as e:
            logger.error(f"Failed to initialize config manager: {e}")
            self._config_manager = None
            return False

    def get(self, key: str, default: Any = None, use_cache: bool = True) -> Any:
        """
        获取配置值，优先从新的配置管理系统获取

        Args:
            key: 配置键名
            default: 默认值
            use_cache: 是否使用缓存

        Returns:
            配置值
        """
        if self._config_manager is not None:
            try:
                import asyncio
                try:
                    # 尝试使用事件循环
                    loop = asyncio.get_event_loop()
                    if loop.is_running():
                        # 如果事件循环正在运行，创建任务
                        task = asyncio.create_task(self._config_manager.get_config(key, default))
                        return asyncio.run_coroutine_threadsafe(task, loop)
                    else:
                        # 如果没有运行的事件循环，直接运行
                        return loop.run_until_complete(self._config_manager.get_config(key, default))
                except RuntimeError:
                    # 在非异步环境中使用同步方法
                    import concurrent.futures
                    with concurrent.futures.ThreadPoolExecutor() as executor:
                        future = executor.submit(asyncio.run, self._config_manager.get_config(key, default))
                        return future.result()
            except Exception as e:
                logger.error(f"Failed to get config from manager: {e}")

        # 回退到环境变量
        if self._fallback_enabled:
            return os.getenv(key, default)

        return default

    def set_fallback_enabled(self, enabled: bool):
        """设置是否启用回退机制"""
        self._fallback_enabled = enabled

    def is_config_manager_available(self) -> bool:
        """检查配置管理器是否可用"""
        return self._config_manager is not None

# 创建全局配置管理器代理实例
_config_proxy = ConfigManagerProxy()

class Config:
    """
    统一配置类 - 兼容新旧配置系统

    优先级：
    1. 新的配置管理系统（数据库）
    2. 环境变量（.env文件）
    3. 默认值
    """

    # 服务器配置
    @property
    def HOST(self) -> str:
        return _config_proxy.get("HOST", "0.0.0.0")

    @property
    def PORT(self) -> int:
        return int(_config_proxy.get("PORT", "8888"))

    @property
    def PREVIEW_MODE(self) -> bool:
        return get_bool_env("PREVIEW_MODE", True)

    @property
    def PREVIEW_TIMEOUT(self) -> int:
        return int(_config_proxy.get("PREVIEW_TIMEOUT", "60"))

    @property
    def DELAY_MODE(self) -> bool:
        return get_bool_env("DELAY_MODE", False)

    @property
    def DELAY_TIME(self) -> int:
        return int(_config_proxy.get("DELAY_TIME", "3"))

    @property
    def KNOWLEDGE_BASE_ENABLED(self) -> bool:
        return get_bool_env("KNOWLEDGE_BASE_ENABLED", False)

    # MCP配置
    @property
    def MCP_PORT(self) -> int:
        return int(_config_proxy.get("MCP_PORT", "9999"))

    @property
    def MCP_TRANSPORT(self) -> str:
        return _config_proxy.get("MCP_TRANSPORT", "sse")

    # 认证配置
    @property
    def API_KEY(self) -> str:
        return _config_proxy.get("API_KEY", "EMPTY")

    @property
    def SESSION_MAX_AGE(self) -> int:
        return int(_config_proxy.get("SESSION_MAX_AGE", "1800"))

    @property
    def MAX_CONVERSATION_MESSAGES(self) -> int:
        return int(_config_proxy.get("MAX_CONVERSATION_MESSAGES", "20"))

    @property
    def MAX_CONVERSATION_TOKENS(self) -> int:
        return int(_config_proxy.get("MAX_CONVERSATION_TOKENS", "8000"))

    @property
    def ENABLE_CONVERSATION_TRUNCATION(self) -> bool:
        return get_bool_env("ENABLE_CONVERSATION_TRUNCATION", True)

    # 模型配置
    @property
    def DEVICE(self) -> str:
        return "cuda:0" if torch.cuda.is_available() else "cpu"

    @property
    def EDGE_TTS_ENABLED(self) -> bool:
        return get_bool_env("EDGE_TTS_ENABLED", False)

    @property
    def EDGE_DEFAULT_VOICE(self) -> str:
        return _config_proxy.get("EDGE_DEFAULT_VOICE", "zh-CN-XiaoyiNeural")

    # 模型按需加载配置 (默认不加载，只在首次调用时加载)
    @property
    def INDEX_TTS_MODEL_ENABLED(self) -> bool:
        return get_bool_env("INDEX_TTS_MODEL_ENABLED", False)

    @property
    def ASR_MODEL_ENABLED(self) -> bool:
        return get_bool_env("ASR_MODEL_ENABLED", False)

    @property
    def RERANK_MODEL_ENABLED(self) -> bool:
        return get_bool_env("RERANK_MODEL_ENABLED", False)

    @property
    def EMBEDDING_MODEL_ENABLED(self) -> bool:
        return get_bool_env("EMBEDDING_MODEL_ENABLED", False)

    @property
    def LLM_MODEL_ENABLED(self) -> bool:
        return get_bool_env("LLM_MODEL_ENABLED", False)

    # 模型路径配置 (按需加载的模型路径)
    @property
    def INDEX_TTS_MODEL_DIR(self) -> str:
        return _config_proxy.get("INDEX_TTS_MODEL_DIR", "/mnt/c/models/IndexTTS-1.5")

    @property
    def ASR_MODEL_DIR(self) -> str:
        return _config_proxy.get("ASR_MODEL_DIR", "/mnt/c/models/SenseVoiceSmall")

    @property
    def RERANK_MODEL_DIR(self) -> str:
        return _config_proxy.get("RERANK_MODEL_DIR", "/mnt/c/models/bge-reranker-base")

    @property
    def EMBEDDING_MODEL_DIR(self) -> str:
        return _config_proxy.get("EMBEDDING_MODEL_DIR", "/mnt/c/models/bge-small-zh-v1.5")

    @property
    def LLM_MODEL_DIR(self) -> str:
        return _config_proxy.get("LLM_MODEL_DIR", "/mnt/c/models/Qwen3-0.6B")

    @property
    def LLM_MODEL_NAME(self) -> str:
        return _config_proxy.get("LLM_MODEL_NAME", "Qwen3-0.6B")

    @property
    def NO_THINK(self) -> bool:
        return get_bool_env("NO_THINK", True)

    @property
    def ASR_PROMPT(self) -> str:
        return _config_proxy.get("ASR_PROMPT", "")

    # LLM模型加载配置
    @property
    def TRUST_REMOTE_CODE(self) -> bool:
        return get_bool_env("TRUST_REMOTE_CODE", True)

    @property
    def USE_HALF_PRECISION(self) -> bool:
        return get_bool_env("USE_HALF_PRECISION", True)

    @property
    def LOW_CPU_MEM_USAGE(self) -> bool:
        return get_bool_env("LOW_CPU_MEM_USAGE", True)

    @property
    def TOKENIZERS_PARALLELISM(self) -> bool:
        return get_bool_env("TOKENIZERS_PARALLELISM", False)

    # LLM模型生成参数配置
    @property
    def MAX_LENGTH(self) -> int:
        return int(_config_proxy.get("MAX_LENGTH", "4096"))

    @property
    def NUM_RETURN_SEQUENCES(self) -> int:
        return int(_config_proxy.get("NUM_RETURN_SEQUENCES", "1"))

    @property
    def TEMPERATURE(self) -> float:
        return float(_config_proxy.get("TEMPERATURE", "0.7"))

    @property
    def TOP_P(self) -> float:
        return float(_config_proxy.get("TOP_P", "0.9"))

    @property
    def REPETITION_PENALTY(self) -> float:
        return float(_config_proxy.get("REPETITION_PENALTY", "1.1"))

    @property
    def LLM_PROMPT(self) -> str:
        prompt = _config_proxy.get("LLM_PROMPT", "")
        if prompt:
            # 处理多行提示词中的转义字符
            return prompt.replace("\\n", "\n")
        return ""

    # EMBEDDING模型配置
    @property
    def TOP_K(self) -> int:
        return int(_config_proxy.get("TOP_K", "3"))

    @property
    def VECTOR_DB_PATH(self) -> str:
        import os
        return os.path.join(os.path.dirname(os.path.abspath(__file__)), "data/vector_db")

    @property
    def DOCS_PATH(self) -> str:
        import os
        return os.path.join(os.path.dirname(os.path.abspath(__file__)), "data/docs")

    @property
    def DOC_CHUNK_SIZE(self) -> int:
        return int(_config_proxy.get("DOC_CHUNK_SIZE", "500"))

    @property
    def DOC_CHUNK_OVERLAP(self) -> int:
        return int(_config_proxy.get("DOC_CHUNK_OVERLAP", "50"))

    @property
    def SUPPORTED_FILE_TYPES(self) -> list:
        return ['.pdf', '.docx', '.txt']

    # RERANK模型配置
    @property
    def RERANK_CANDIDATE_FACTOR(self) -> int:
        return int(_config_proxy.get("RERANK_CANDIDATE_FACTOR", "10"))

    @property
    def RERANK_BATCH_SIZE(self) -> int:
        return int(_config_proxy.get("RERANK_BATCH_SIZE", "16"))

    # IndexTTS-1.5引擎配置
    @property
    def INDEX_TTS_FAST_ENABLED(self) -> bool:
        return get_bool_env("INDEX_TTS_FAST_ENABLED", False)

    @property
    def INDEX_TTS_FAST_MAX_TOKENS(self) -> int:
        return int(_config_proxy.get("INDEX_TTS_FAST_MAX_TOKENS", "50"))

    @property
    def INDEX_TTS_FAST_BATCH_SIZE(self) -> int:
        return int(_config_proxy.get("INDEX_TTS_FAST_BATCH_SIZE", "16"))

    @property
    def INDEX_TTS_STREAMING_MIN_SENTENCE_CHARS(self) -> int:
        return int(_config_proxy.get("INDEX_TTS_STREAMING_MIN_SENTENCE_CHARS", "15"))

    @property
    def INDEX_TTS_DEVICE(self) -> str:
        device = _config_proxy.get("INDEX_TTS_DEVICE", "")
        if device:
            return device
        return "cuda" if torch.cuda.is_available() else "cpu"

    @property
    def INDEX_TTS_MAX_WORKERS(self) -> int:
        return int(_config_proxy.get("INDEX_TTS_MAX_WORKERS", "2"))

    @property
    def INDEX_TTS_TIMEOUT(self) -> int:
        return int(_config_proxy.get("INDEX_TTS_TIMEOUT", "60"))

    @property
    def INDEX_TTS_SUPPORTED_VOICES(self) -> list:
        return ["default"]

    @property
    def INDEX_TTS_REFERENCE_AUDIO(self) -> str:
        return _config_proxy.get("INDEX_TTS_REFERENCE_AUDIO", "default.wav")

    # MySQL数据库配置
    @property
    def MYSQL_HOST(self) -> str:
        return _config_proxy.get("MYSQL_HOST", "172.21.48.1")

    @property
    def MYSQL_PORT(self) -> int:
        return int(_config_proxy.get("MYSQL_PORT", 3306))

    @property
    def MYSQL_USER(self) -> str:
        return _config_proxy.get("MYSQL_USER", "root")

    @property
    def MYSQL_PASSWORD(self) -> str:
        return _config_proxy.get("MYSQL_PASSWORD", "root")

    @property
    def MYSQL_DATABASE(self) -> str:
        return _config_proxy.get("MYSQL_DATABASE", "any4any")

    # 数据库功能配置
    @property
    def QUERY_CLEANING(self) -> bool:
        return get_bool_env("QUERY_CLEANING", True)

    # MySQL连接池配置
    @property
    def DB_POOL_ENABLED(self) -> bool:
        return get_bool_env("DB_POOL_ENABLED", True)

    @property
    def DB_POOL_SIZE(self) -> int:
        return int(_config_proxy.get("DB_POOL_SIZE", "15"))

    @property
    def DB_POOL_TIMEOUT(self) -> int:
        return int(_config_proxy.get("DB_POOL_TIMEOUT", "30"))

    @property
    def DB_POOL_RECYCLE(self) -> int:
        return int(_config_proxy.get("DB_POOL_RECYCLE", "1800"))

    @property
    def DB_POOL_PRE_PING(self) -> bool:
        return get_bool_env("DB_POOL_PRE_PING", True)

    # 熔断器配置
    @property
    def DB_CIRCUIT_BREAKER_THRESHOLD(self) -> int:
        return int(_config_proxy.get("DB_CIRCUIT_BREAKER_THRESHOLD", "5"))

    @property
    def DB_CIRCUIT_BREAKER_TIMEOUT(self) -> int:
        return int(_config_proxy.get("DB_CIRCUIT_BREAKER_TIMEOUT", "60"))

    # 重试机制配置
    @property
    def DB_RETRY_ENABLED(self) -> bool:
        return get_bool_env("DB_RETRY_ENABLED", True)

    @property
    def DB_RETRY_MAX_ATTEMPTS(self) -> int:
        return int(_config_proxy.get("DB_RETRY_MAX_ATTEMPTS", "3"))

    @property
    def DB_RETRY_BACKOFF_FACTOR(self) -> float:
        return float(_config_proxy.get("DB_RETRY_BACKOFF_FACTOR", "2"))

    @property
    def DB_RETRY_MAX_DELAY(self) -> int:
        return int(_config_proxy.get("DB_RETRY_MAX_DELAY", "30"))

    # 工具系统配置

    # SQL数据库配置 (复用现有MySQL配置)
    @property
    def SQL_DB_TYPE(self) -> str:
        return _config_proxy.get("SQL_DB_TYPE", "mysql")

    @property
    def SQL_DB_HOST(self) -> str:
        return self.MYSQL_HOST

    @property
    def SQL_DB_PORT(self) -> int:
        return self.MYSQL_PORT

    @property
    def SQL_DB_USERNAME(self) -> str:
        return self.MYSQL_USER

    @property
    def SQL_DB_PASSWORD(self) -> str:
        return self.MYSQL_PASSWORD

    @property
    def SQL_DB_DATABASE(self) -> str:
        return self.MYSQL_DATABASE

    # 工具系统配置
    @property
    def TOOLS_ENABLED(self) -> bool:
        return get_bool_env("TOOLS_ENABLED", True)

    # NL2SQL工具配置
    @property
    def NL2SQL_ENABLED(self) -> bool:
        return get_bool_env("NL2SQL_ENABLED", True)

    # 时间工具配置
    @property
    def TIME_TOOLS_ENABLED(self) -> bool:
        return get_bool_env("TIME_TOOLS_ENABLED", True)

    @property
    def TIME_ZONE(self) -> str:
        return _config_proxy.get("TIME_ZONE", "Asia/Shanghai")

    @property
    def TIME_FORMAT_DEFAULT(self) -> str:
        return _config_proxy.get("TIME_FORMAT_DEFAULT", "%Y-%m-%d %H:%M:%S")

    # 钉钉配置
    @property
    def DINGTALK_ENABLED(self) -> bool:
        return get_bool_env("DINGTALK_ENABLED", False)

    @property
    def CLIENT_ID(self) -> str:
        return _config_proxy.get("CLIENT_ID", "")

    @property
    def CLIENT_SECRET(self) -> str:
        return _config_proxy.get("CLIENT_SECRET", "")

    @property
    def ROBOT_CODE(self) -> str:
        return _config_proxy.get("ROBOT_CODE", "")

    @property
    def DINGTALK_PORT(self) -> str:
        return _config_proxy.get("DINGTALK_PORT", "6666")

    # any4dh 数字人配置
    @property
    def ANY4DH_ENABLED(self) -> bool:
        return get_bool_env("ANY4DH_ENABLED", False)

    @property
    def ANY4DH_USE_UNIFIED_INTERFACE(self) -> bool:
        return get_bool_env("ANY4DH_USE_UNIFIED_INTERFACE", True)

    @property
    def ANY4DH_TRANSPORT(self) -> str:
        return _config_proxy.get("ANY4DH_TRANSPORT", "stream")

    @property
    def ANY4DH_MODEL(self) -> str:
        return _config_proxy.get("ANY4DH_MODEL", "wav2lip")

    @property
    def ANY4DH_AVATAR_ID(self) -> str:
        return _config_proxy.get("ANY4DH_AVATAR_ID", "001")

    @property
    def ANY4DH_BATCH_SIZE(self) -> int:
        return int(_config_proxy.get("ANY4DH_BATCH_SIZE", "16"))

    @property
    def ANY4DH_FPS(self) -> int:
        return int(_config_proxy.get("ANY4DH_FPS", "50"))

    @property
    def ANY4DH_TTS(self) -> str:
        return _config_proxy.get("ANY4DH_TTS", "edgetts")

    @property
    def ANY4DH_REF_FILE(self) -> str:
        return _config_proxy.get("ANY4DH_REF_FILE", "zh-CN-YunxiaNeural")

    @property
    def ANY4DH_REF_TEXT(self) -> str:
        return _config_proxy.get("ANY4DH_REF_TEXT", "")

    @property
    def ANY4DH_TTS_SERVER(self) -> str:
        return _config_proxy.get("ANY4DH_TTS_SERVER", "http://127.0.0.1:9880")

    @property
    def ANY4DH_MAX_SESSION(self) -> int:
        return int(_config_proxy.get("ANY4DH_MAX_SESSION", "1"))

    @property
    def ANY4DH_WAV2LIP_MODEL_DIR(self) -> str:
        return _config_proxy.get("ANY4DH_WAV2LIP_MODEL_DIR", "/mnt/c/models/wav2lip256/wav2lip.pth")

    @property
    def ANY4DH_AVATARS_DIR(self) -> str:
        return _config_proxy.get("ANY4DH_AVATARS_DIR", "data/avatars")

    # any4dh 语音知识库配置
    @property
    def ANY4DH_VOICE_KB_ENABLED(self) -> bool:
        return get_bool_env("ANY4DH_VOICE_KB_ENABLED", False)

    @property
    def ANY4DH_VOICE_KB_LANGUAGE(self) -> str:
        return _config_proxy.get("ANY4DH_VOICE_KB_LANGUAGE", "zh")

    @property
    def ANY4DH_VOICE_KB_FALLBACK_TO_TTS(self) -> bool:
        return get_bool_env("ANY4DH_VOICE_KB_FALLBACK_TO_TTS", True)

    @property
    def ANY4DH_VOICE_KB_SEMANTIC_THRESHOLD(self) -> float:
        return float(_config_proxy.get("ANY4DH_VOICE_KB_SEMANTIC_THRESHOLD", "0.1"))

    @property
    def VOICE_KB_CSV_PATH(self) -> str:
        return _config_proxy.get("VOICE_KB_CSV_PATH", "data/csv/en_voice_list.csv")

    @property
    def VOICE_KB_AUDIO_DIR(self) -> str:
        return _config_proxy.get("VOICE_KB_AUDIO_DIR", "data/en_answer")

    # 外部LLM API配置 (OpenAI兼容格式)
    @property
    def LLM_SERVER_TYPE(self) -> str:
        return _config_proxy.get("LLM_SERVER_TYPE", "local")

    @property
    def EXTERNAL_API_KEY(self) -> str:
        return _config_proxy.get("EXTERNAL_API_KEY", "")

    @property
    def API_BASE_URL(self) -> str:
        return _config_proxy.get("API_BASE_URL", "")

    @property
    def MODEL_NAME(self) -> str:
        return _config_proxy.get("MODEL_NAME", "")

    @property
    def API_TIMEOUT(self) -> int:
        return int(_config_proxy.get("API_TIMEOUT", "120"))

    @property
    def MAX_TOKENS(self) -> int:
        return int(_config_proxy.get("MAX_TOKENS", "8192"))

    @property
    def STREAM_ENABLED(self) -> bool:
        return get_bool_env("STREAM_ENABLED", True)

    @property
    def API_MAX_RETRIES(self) -> int:
        return int(_config_proxy.get("API_MAX_RETRIES", "3"))

    @property
    def API_RETRY_DELAY(self) -> float:
        return float(_config_proxy.get("API_RETRY_DELAY", "1.0"))

    # ADB工具配置
    @property
    def ADB_TOOLS_ENABLED(self) -> bool:
        return get_bool_env("ADB_TOOLS_ENABLED", True)

    @property
    def ADB_COMMAND_PATH(self) -> str:
        return _config_proxy.get("ADB_COMMAND_PATH", "/mnt/c/platform-tools/adb.exe")

    @property
    def ADB_TIMEOUT(self) -> int:
        return int(_config_proxy.get("ADB_TIMEOUT", 30))

    @property
    def ADB_RETRY_COUNT(self) -> int:
        return int(_config_proxy.get("ADB_RETRY_COUNT", 3))

    # Web搜索工具配置
    @property
    def WEB_SEARCH_ENABLED(self) -> bool:
        return get_bool_env("WEB_SEARCH_ENABLED", True)

    @property
    def WEB_SEARCH_PROXY_URL(self) -> str:
        return _config_proxy.get("WEB_SEARCH_PROXY_URL", "http://127.0.0.1:10809")

    @property
    def WEB_SEARCH_USE_PROXY(self) -> bool:
        return get_bool_env("WEB_SEARCH_USE_PROXY", False)

    @property
    def WEB_SEARCH_RESULT_LIMIT(self) -> int:
        return int(_config_proxy.get("WEB_SEARCH_RESULT_LIMIT", "10"))

    @property
    def WEB_SEARCH_TIMEOUT(self) -> int:
        return int(_config_proxy.get("WEB_SEARCH_TIMEOUT", "30"))

    @property
    def WEB_SEARCH_RATE_LIMIT(self) -> int:
        return int(_config_proxy.get("WEB_SEARCH_RATE_LIMIT", "2"))

    @property
    def WEB_SEARCH_PRIMARY_ENGINE(self) -> str:
        return _config_proxy.get("WEB_SEARCH_PRIMARY_ENGINE", "bing").lower()

    @property
    def WEB_SEARCH_FALLBACK_ENGINES(self) -> list:
        engines = _config_proxy.get("WEB_SEARCH_FALLBACK_ENGINES", "duckduckgo")
        return [engine.strip() for engine in engines.split(",") if engine.strip()]

    @property
    def WEB_SEARCH_MAX_RETRIES(self) -> int:
        return int(_config_proxy.get("WEB_SEARCH_MAX_RETRIES", "3"))

    @property
    def WEB_SEARCH_RETRY_DELAY(self) -> float:
        return float(_config_proxy.get("WEB_SEARCH_RETRY_DELAY", "1.0"))

    # 确保目录存在
    def _ensure_directories(self):
        """确保必要的目录存在"""
        import os
        directories = [
            self.ASR_MODEL_DIR,
            self.RERANK_MODEL_DIR,
            self.LLM_MODEL_DIR,
            self.EMBEDDING_MODEL_DIR,
            self.VECTOR_DB_PATH,
            self.DOCS_PATH,
            self.INDEX_TTS_MODEL_DIR,
            self.ANY4DH_AVATARS_DIR,
            os.path.dirname(self.ANY4DH_WAV2LIP_MODEL_DIR)
        ]

        for directory in directories:
            if directory:
                os.makedirs(directory, exist_ok=True)

    def __init__(self):
        self._ensure_directories()

# 创建全局配置实例
Config = Config()

# 向后兼容的全局函数
async def initialize_config_system(db_config: Optional[dict] = None):
    """初始化配置管理系统"""
    return await _config_proxy.initialize(db_config)

def get_config_manager():
    """获取配置管理器实例"""
    return _config_proxy._config_manager

def is_config_manager_available() -> bool:
    """检查配置管理器是否可用"""
    return _config_proxy.is_config_manager_available()